接續前篇說的介面如下
    public interface IChain<T>
    {
        IChain<TNext> Then<TNext>(Func<T,TNext> next);
        IChainAsync<TNext> WaitThen<TNext>(Func<T,Task<TNext>> next);
        T Result { get; }
    }
    public interface IChainAsync<T>
    {
        IChainAsync<TNext> Then<TNext>(Func<T,TNext> next);
        IChainAsync<TNext> WaitThen<TNext>(Func<T,Task<TNext>> next);
        Task<T> Result { get; }
    }
這裡運用到了 Task 與 Func<>
我先來簡單介紹一下 Task 與 Func 給不熟悉的人
首先 Func<> 與 Action極其多個泛行型別 皆屬於委派
而Action 是無回傳值委派,其泛型型別參數皆屬於該委派參數型別
而Func<>則是具回傳值委派,其泛型參數至少一存在一個為回傳型別參數並放在最後一位,其餘皆屬於委派參數型別
而 Task 則是與這兩個東西息息相關
Task 主要分為 Task 與 Task<> 現階段較常見的都用 Task.Run 來建立
而建立方法如果帶入 Action 則會回傳 Task
如果帶入 Func<> 則會回傳 Task<>
而如果簡單描述 Func<> 與 Task<> 的差別的話
Func<> 是執行當下開始動作,然後等結果
Task<> 則是建立當下就開始動作,然等結果有了之後取結果
如果把他們合再一起就會變成
Task<Func<>> 這其實沒什麼意思,因為 Task 本身就是用Func<>建立起的
Func<Task<>> 這個就很有趣了,這就成了一個延遲Task 開始運行並且可由使用端來決定開始時間的微妙結構
我們延續之前的步驟,依序說明每一段個代表的意思所以用上什麼樣的實作
    /// <summary>
    /// 非同步的方法責任練
    /// </summary>
    public class Chain<T> : IChain<T>
    {
        private T _current;
        internal Chain(T current)
        {
            _current = current;
        }
        /// <summary>
        /// 接著走下一步到下一個階段
        /// </summary>
        /// <param name="next">下一步</param>
        /// <returns>下一個階段</returns>
        public IChain<TNext> Then<TNext>(Func<T, TNext> next)
            => new Chain<TNext>(GetNextValue<TNext>(next));
        /// <summary>
        /// 接著走下一步到下一個非同步階段
        /// </summary>
        /// <param name="next">下一步</param>
        /// <returns>分同步階段</returns>
        public IChainAsync<TNext> ThenAsync<TNext>(Func<T, Task<TNext>> next)
            => new ChainAsync<TNext>(Task.Run(() => next(_current)));
        /// <summary>
        /// 取得下一個階段的回傳值
        /// </summary>
        /// <param name="next">下一步</param>
        /// <returns>回傳值</returns>
        private TNext GetNextValue<TNext>(Func<T,TNext> next)
            => next(_current);
        /// <summary>
        /// 取得非同步的下一個階段的回傳值
        /// </summary>
        /// <param name="next">下一步</param>
        /// <returns>非同步的回傳值</returns>
        private Task<TNext> GetNextValueAsync<TNext>(Func<T, Task<TNext>> next)
            => next(_current);
        public T Result => _current;
    }
    /// <summary>
    /// 非同步的方法責任練
    /// </summary>
    public class ChainAsync<T> : IChainAsync<T>
    {
        private Task<T> _task;
        internal ChainAsync(Task<T> task)
        {
            _task = task;
        }
        /// <summary>
        /// 用等待的結果,接著走下一步到下一個非同步階段
        /// </summary>
        /// <param name="next"></param>
        /// <returns></returns>
        public IChainAsync<TNext> WaitThen<TNext>(Func<T,Task<TNext>> next)
            => new ChainAsync<TNext>(GetNextValueAsync<TNext>(next));
        /// <summary>
        /// 用等待的結果,接著走下一步到下一個階段
        /// </summary>
        /// <param name="next"></param>
        /// <returns></returns>
        public IChainAsync<TNext> Then<TNext>(Func<T,TNext> next)
            => new ChainAsync<TNext>(GetNextValue<TNext>(next));
        /// <summary>
        /// 取得下一個結果
        /// </summary>
        /// <param name="next"></param>
        /// <returns></returns>
        async private Task<TNext> GetNextValue<TNext>(Func<T,TNext> next)
            => next(await _task);
        /// <summary>
        /// 取得下一個非同步的結果
        /// </summary>
        /// <param name="next"></param>
        /// <returns></returns>
        async private Task<TNext> GetNextValueAsync<TNext>(Func<T, Task<TNext>> next)
            => await next(await _task);
            
        public Task<T> Result => _task;
    }
直至目前我們已經近乎要達成我們原本期望的情況
問題還差在同步方法串中不同存在相同名稱不同回傳值的方法
也就是說我們不能在同一個類別內同時寫
IChain<TNext> Then<TNext>(Func<T,TNext> next);
IChainAsync<TNext> Then<TNext>(Func<T,Task<TNext>> next);
不過這是小事,下一次就來完成我所期望的描述法吧.
 - 本次範例程式碼以更新至Github
 - 在下這次偷偷廣告我個人對於 Task的觀點
Builder vs Factory : Builder 通常可以提供我們Build的操作設定,而Factory則只能提供簡單標籤
Configure vs Convention : Configure 通常來自於外部定義,Convention則為通常為內部預設定義